#include "headers/isr.h"
#include "headers/idt.h"
#include "../tools/headers/common.h"
#include "../api/headers/io.h"
#include "../multitasking/headers/task.h"
#include "../multitasking/headers/timer.h"

extern global_int;
extern interrupt_handlers[256];
extern task_t* current_task;
extern task_t* killer_task;
extern BOOL critical_section;
s8int *exception_messages[] =
{
    "Division By Zero",
    "Debug",
    "Non Maskable Interrupt",
    "Breakpoint",
    "Into Detected Overflow",
    "Out of Bounds",
    "Invalid Opcode",
    "No Coprocessor",
    "Double Fault",
    "Coprocessor Segment Overrun",
    "Bad TSS",
    "Segment Not Present",
    "Stack Fault",
    "General Protection Fault",
    "Page Fault",
    "Unknown Interrupt",
    "Coprocessor Fault",
    "Alignment Check",
    "Machine Check"
};

void isr_0();
void isr_1();
void isr_2();
void isr_3();
void isr_4();
void isr_5();
void isr_6();
void isr_7();
void isr_8();
void isr_9();
void isr_10();
void isr_11();
void isr_12();
void isr_13();
void isr_14();
void isr_15();
void isr_16();
void isr_17();
void isr_18();
void isr_19();
void isr_20();
void isr_21();
void isr_22();
void isr_23();
void isr_24();
void isr_25();
void isr_26();
void isr_27();
void isr_28();
void isr_29();
void isr_30();
void isr_31();

void install_isrs()
{
	idt_set_gate(0, (u32int)isr_0, 0x08, 0x8E);
	idt_set_gate(1, (u32int)isr_1, 0x08, 0x8E);
	idt_set_gate(2, (u32int)isr_2, 0x08, 0x8E);
	idt_set_gate(3, (u32int)isr_3, 0x08, 0x8E);
	idt_set_gate(4, (u32int)isr_4, 0x08, 0x8E);
	idt_set_gate(5, (u32int)isr_5, 0x08, 0x8E);
	idt_set_gate(6, (u32int)isr_6, 0x08, 0x8E);
	idt_set_gate(7, (u32int)isr_7, 0x08, 0x8E);
	idt_set_gate(8, (u32int)isr_8, 0x08, 0x8E);
	idt_set_gate(9, (u32int)isr_9, 0x08, 0x8E);
	idt_set_gate(10, (u32int)isr_10, 0x08, 0x8E);
	idt_set_gate(11, (u32int)isr_11, 0x08, 0x8E);
	idt_set_gate(12, (u32int)isr_12, 0x08, 0x8E);
	idt_set_gate(13, (u32int)isr_13, 0x08, 0x8E);
	idt_set_gate(14, (u32int)isr_14, 0x08, 0x8E);
	idt_set_gate(15, (u32int)isr_15, 0x08, 0x8E);
	idt_set_gate(16, (u32int)isr_16, 0x08, 0x8E);
	idt_set_gate(17, (u32int)isr_17, 0x08, 0x8E);
	idt_set_gate(18, (u32int)isr_18, 0x08, 0x8E);
	idt_set_gate(19, (u32int)isr_19, 0x08, 0x8E);
	idt_set_gate(20, (u32int)isr_20, 0x08, 0x8E);
	idt_set_gate(21, (u32int)isr_21, 0x08, 0x8E);
	idt_set_gate(22, (u32int)isr_22, 0x08, 0x8E);
	idt_set_gate(23, (u32int)isr_23, 0x08, 0x8E);
	idt_set_gate(24, (u32int)isr_24, 0x08, 0x8E);
	idt_set_gate(25, (u32int)isr_25, 0x08, 0x8E);
	idt_set_gate(26, (u32int)isr_26, 0x08, 0x8E);
	idt_set_gate(27, (u32int)isr_27, 0x08, 0x8E);
	idt_set_gate(28, (u32int)isr_28, 0x08, 0x8E);
	idt_set_gate(29, (u32int)isr_29, 0x08, 0x8E);
	idt_set_gate(30, (u32int)isr_30, 0x08, 0x8E);
	idt_set_gate(31, (u32int)isr_31, 0x08, 0x8E);
}

void isr_handler(registers_type registers)
{
	virtual_console_type* tmp = getCurrentVirtualConsole();
	
	
	setCurrentVirtualConsole(killer_task->console);
	if (interrupt_handlers[registers.interrupt_number] != 0)
    {
        isr_type handler = interrupt_handlers[registers.interrupt_number];
        handler(registers);
    }
    else if (registers.interrupt_number < 32)
    {
        printf("Unhandled exception (%d) ocurred: %s\n",registers.interrupt_number, exception_messages[registers.interrupt_number]);
		printf("Error code: %d\n", registers.error_code);
	}
	
	if(current_task->id <=3)
			K_PANIC(exception_messages[registers.interrupt_number]);
	
	setCurrentVirtualConsole(tmp);
	if (registers.interrupt_number < 32) //Not a syscall
	{
		if(getpid() > 2) //If not kernel or shell
		{
			
			asm volatile ("sti");
			critical_section = false;
			current_task->state = KILLED;
			raise_timer_int();
		}
		for(;;);
	}
} 
